/******************************************************************************
Copyright (c) 2012, Silicon Laboratories, Inc.

Filename : USB_BL_ISR.c
Project  : USB Bootloader (USB_BL)
Created  : 02 JUN 2004 / PKC
Devices  : C8051F320/1/6/7/'F34x/'F38x
Toolchain: Keil

Description:
Contains the USBXpress API ISR and functions that use the USBXpress firmware
API to read & write data from & to the USB bus.

Revision History:

01NOV2012-SHY:
-Add codes for F38x 
06JUL2007-PKC:
-Included USB_BL_ISR.h
05DEC2006-PKC:
-Added conditional compilation for USBXpress_ISR vector depending on the MCU.

******************************************************************************/

// ===========================================================================
// *** Includes ***
// ===========================================================================
#include "USB_BL_Main.h"
#include "USB_BL_QueueMgmt.h"
#include "USB_BL_ISR.h"
#include "USB_API.h"

// ===========================================================================
// *** Global Variables ***
// ===========================================================================
BYTE xdata OUT_PACKET[BULK_PACKET_SIZE] _at_ MEM_OUT_PACKET;
BYTE xdata IN_PACKET[BULK_PACKET_SIZE]  _at_ MEM_IN_PACKET;

BYTE TxCompleteFlag  = 1;

// ===========================================================================
// *** Function Definitions ***
// ===========================================================================

// ---------------------------------------------------------------------------
// >>> Handle_In1 <<<
//
// Populates the IN_PACKET array with values from the TxQueue and then loads
// the current value from In_Packet onto the Endpoint 1 fifo, after an
// interrupt is received from the last packet being transmitted.
// Note: The TxCompleteFlag transforms the interrupt-driven transmit scheme to
// a polled transmit scheme.
// ---------------------------------------------------------------------------
void Handle_In1(void)
{
   BYTE i = 0;
   while((!_TxQueueEmpty) && (i < BULK_PACKET_SIZE))
      IN_PACKET[i++] = GetNextTxByte();
   if(i != 0)
   {
      while(!TxCompleteFlag);    // wait till tx complete
      TxCompleteFlag = 0;        // reset flag
      Block_Write(IN_PACKET, i); // write new block
   }
}

// ---------------------------------------------------------------------------
// >>> Handle_Out2 <<<
//
// Takes the received packet from the host off the fifo and puts it into
// the Out_Packet array and then enqueues the values from the array in the
// RxQueue.
// ---------------------------------------------------------------------------
void Handle_Out2(void)
{
   BYTE BytesRead, x;

   if(((RxHead <= RxTail) ? (RX_MAX_QUEUE - RxTail + RxHead) :
      (RxHead - RxTail)) >= BULK_PACKET_SIZE)
   {
      BytesRead = Block_Read(OUT_PACKET, BULK_PACKET_SIZE); //read new block
      for(x=0;x<BytesRead;x++)
      {
         EnRxQueue(OUT_PACKET[x]);  //enqueue the bytes read into RxQueue
      }
   }
}

// ===========================================================================
// *** ISR Definitions ***
// ===========================================================================

// ---------------------------------------------------------------------------
// => USBXpress_ISR <=
//
// The bootloader project's USB API ISR that should handle interrupt 16/17
// ('F32x/'F34x) generated by USBXpress. But interrupt 16 is first handled by
// a small piece of assembly code present in the STARTUP.A51 file, which when
// the device is in bootload mode, redirects that interrupt to
// interrupt 17/18 ('F32x/'F34x).
// ---------------------------------------------------------------------------
#if defined(_C8051F320_1_) || defined(_C8051F326_7_)
void USBXpress_ISR(void) interrupt 17
#endif

#if defined(_C8051F34X_32K_) || defined(_C8051F34X_64K_)
void USBXpress_ISR(void) interrupt 18
#endif
#if defined(_C8051F38X_32K_) || defined(_C8051F38X_64K_)
void USBXpress_ISR(void) interrupt 21
#endif
{
   BYTE IntVal = Get_Interrupt_Source();  // Query the cause of this interrupt

   if (IntVal & USB_RESET)
   {
   }

   if (IntVal & TX_COMPLETE)
   {                                      // Set flag to indicate that the
      TxCompleteFlag = 1;                 // previous trasmit is complete
   }

   if (IntVal & RX_COMPLETE)
   {                                      // On receiving new data, make call
      Handle_Out2();                      // to move the data from the FIFO
   }

   if ( IntVal & (FIFO_PURGE | DEVICE_OPEN | DEVICE_CLOSE) )
   {
      InitQueues();
      TxCompleteFlag = 1;
   }

   if (IntVal & DEV_CONFIGURED)
   {
   }

   if (IntVal & DEV_SUSPEND)
   {
      USB_Suspend();
   }

}

// ===========================================================================
// *** END OF FILE *** USB_BL_ISR.c ***
// ===========================================================================